package main

import (
	"fmt"
	"sync"
	"time"
)

func producer(id int, ch chan<- int, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < 5; i++ {
		fmt.Printf("Producer %d produced: %d\n", id, i)
		ch <- i
		time.Sleep(time.Millisecond * 100)
	}
}

func consumer(id int, ch <-chan int, wg *sync.WaitGroup) {
	defer wg.Done()
	/*
		你站在传送带前等包裹
		传送带还在运行（channel没关闭）
		你就一直等，即使暂时没有包裹
	*/
	for num := range ch { // 只要channel不关闭，我就一直在这里等新数据 就是这行在无限等待！
		fmt.Printf("Consumer %d consumed: %d\n", id, num)
		time.Sleep(time.Millisecond * 300)
	}

	/*
			问题出现：

		10个数据很快被3个消费者分完了
		但消费者还在 for range ch 里等第11个数据
		没人告诉消费者"没有更多数据了"
		所以消费者永远等下去

		就像现实生活中的例子：
		餐厅场景：
		厨师做了10道菜（生产者完成）
		3个顾客吃了10道菜
		但顾客还坐在桌前等第11道菜
		没人告诉顾客"厨房已经下班了"
		结果：顾客永远等下去
	*/
}

func main() {
	ch := make(chan int, 10)
	// 等待一组goroutine完成他们的工作
	// 老师等所有学生完成作业：
	//老师：WaitGroup
	//学生：各个goroutine
	//完成作业：goroutine执行完毕
	// wg.Add(1) // 告诉WaitGroup：有一个新任务开始了
	// wg.Done() // 告诉WaitGroup：我这个任务完成了
	// wg.Wait() // 等待所有任务完成, 阻塞等待，直到所有任务都调用了Done()
	var producerWg sync.WaitGroup
	var consumerWg sync.WaitGroup

	// 启动2个生产者
	for i := 1; i <= 2; i++ {
		producerWg.Add(1)
		go producer(i, ch, &producerWg)
	}

	// 启动3个消费者
	for i := 1; i <= 3; i++ {
		consumerWg.Add(1)
		go consumer(i, ch, &consumerWg)
	}

	// 关键修复：先等待生产者完成，再关闭channel
	// 这样可以确保所有生产者都已经将数据发送到channel中
	producerWg.Wait()
	close(ch)

	// 然后等待消费者完成
	consumerWg.Wait()
}
